package server.business.service.Impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.toolkit.LambdaUtils;
import org.apache.logging.log4j.util.Strings;
import server.business.pojo.BloodStock;
import server.business.service.BloodStockService;
import server.business.mapper.BloodStockMapper;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Galaxy
 * @description 针对表【blood_stock】的数据库操作Service实现
 * @createDate 2022-11-08 12:46:24
 */
@Service("bloodStockService")
public class BloodStockServiceImpl extends ServiceImpl<BloodStockMapper, BloodStock>
        implements BloodStockService{
    /**
     * 处理sql查询字段名 拼接wrapper和lambdawrapper查询项
     * @param columns
     * @SFunction PatientTransfusionInformation
     * @return
     */
    private String getParamSql(SFunction<BloodStock, ?>... columns) {
        return Arrays.stream(columns).map(c -> StrUtil.toUnderlineCase(LambdaUtils.getName(c))).collect(Collectors.joining(StringPool.COMMA, StringPool.SPACE, StringPool.SPACE));
    }
    @Resource
    private  BloodStockMapper bloodStockMapper;
    /**
     *
     * @param
     * @description 血液库存查询
     * @return 更新状态后的所有血液库存
     */
    @Override
    public IPage<BloodStock> listBlood(int currentPage, int pageSize, BloodStock user) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        String nowDate = formatter.format(date);
//        更新目前时间已经过期的血液状态（出库的不更新）
        LambdaUpdateWrapper<BloodStock> bloodStockWrapper = Wrappers.<BloodStock>lambdaUpdate()
                .eq(BloodStock::getState,"2")
                .le(BloodStock::getFailureTime,nowDate)
                .set(BloodStock::getState,"26");
        bloodStockMapper.update(null,bloodStockWrapper);
        QueryWrapper<BloodStock> list = new QueryWrapper<>();
        IPage page = new Page(currentPage,pageSize);
        bloodStockMapper.selectPage(page,list);
        return page;
    }



    /**
     * 血型筛选血液库存
     * @param abo,String,except
     * @return 特定血型的所有血液库存
     */
    @Override
    public List<BloodStock> listBloodAboRh(String abo, String rh,String except) {
        QueryWrapper<BloodStock> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(BloodStock::getAboBloodType,abo)
                .eq(BloodStock::getRhBloodType,rh)
                .eq(BloodStock::getState,except);
        List<BloodStock> list = this.list(wrapper);
        return list;
    }

    /**
     * 状态筛选血液库存
     * @param bloodCon
     * @return 筛选是否过期的所有血液库存
     */
    @Override
    public IPage<BloodStock> listBloodUseful(int currentPage, int pageSize,String bloodCon) {
        QueryWrapper<BloodStock> wrapper = new QueryWrapper<>();
        Date date = new Date(System.currentTimeMillis());
        System.out.println(bloodCon);
        if(bloodCon.equals("1")){
            System.out.println(111);
            wrapper
                    .lambda()
                    .eq(BloodStock::getState,2)
                    .gt(BloodStock::getFailureTime,date);
        }
        IPage page = new Page(currentPage,pageSize);
        bloodStockMapper.selectPage(page,wrapper);
        return page;
    }
    /**
     * 血液库存统计分析
     * @param
     * @return 统计各类型未过期血液数量
     */
    @Override
    public List<Map<String, Object>> getVarityNumber() {
        Date date = new Date(System.currentTimeMillis());
        QueryWrapper<BloodStock> bloodNumber =new QueryWrapper<>();
        bloodNumber
                .select(
                        getParamSql(BloodStock::getBloodVariety),
                        getParamSql(BloodStock::getAboBloodType),
                        getParamSql(BloodStock::getRhBloodType),
                        "IFNULL(sum(unit_volume),0)  as totalHp")

                .lambda()
                .groupBy(
                        BloodStock::getAboBloodType,
                        BloodStock::getRhBloodType,
                        BloodStock::getBloodVariety)
                .gt(BloodStock::getFailureTime,date)
                .eq(BloodStock::getState,"2")
        ;
        List<Map<String, Object>> maps = this.listMaps(bloodNumber);
        System.out.println(maps.getClass().toString());
        return maps;

    }
    /**
     * 血液库存搜索
     * @param
     * @return 指定ID的血液库存
     */
    @Override
    public List<BloodStock> listBloodAlone(String blooId) {
        QueryWrapper<BloodStock> wrapper = new QueryWrapper<>();
        wrapper
                .lambda()
                .eq(BloodStock::getBloodId, blooId);
        List<BloodStock> list = this.list(wrapper);
        return list;
    }
    /**
     * 血液出入量和失效量统计查询
     * @param
     * @return 各种血液出入量和失效量
     */
    @Override
    public List<Map<String, Object>> getBloodInReport(Timestamp startTime, Timestamp endTime) {
        QueryWrapper<BloodStock> wrapperIn = new QueryWrapper<>();
        wrapperIn
                .select(
                        getParamSql(BloodStock::getBloodVariety),
                        getParamSql(BloodStock::getAboBloodType),
                        getParamSql(BloodStock::getRhBloodType),
                        "IFNULL(sum(unit_volume),0)  as InHp")
                .lambda()
                .between(BloodStock::getInboundTime,startTime,endTime)
                .groupBy(
                        BloodStock::getAboBloodType,
                        BloodStock::getRhBloodType,
                        BloodStock::getBloodVariety);
        List<Map<String, Object>> listIn = this.listMaps(wrapperIn);
//        System.out.println("listIn:"+listIn);
        return listIn;
    }

    @Override
    public List<Map<String, Object>> getBloodFailReport(Timestamp startTime, Timestamp endTime) {
        QueryWrapper<BloodStock> wrapperFail = new QueryWrapper<>();
        wrapperFail
                .select(
                        getParamSql(BloodStock::getBloodVariety),
                        getParamSql(BloodStock::getAboBloodType),
                        getParamSql(BloodStock::getRhBloodType),
                        "IFNULL(sum(unit_volume),0)  as FailHp")
                .lambda()
                .between(BloodStock::getInboundTime,startTime,endTime)
                .eq(BloodStock::getState,'3')
                .groupBy(
                        BloodStock::getAboBloodType,
                        BloodStock::getRhBloodType,
                        BloodStock::getBloodVariety);
        List<Map<String, Object>> listFail = this.listMaps(wrapperFail);
//        System.out.println("listFail:"+listFail);
        return listFail;
    }

    /**
     * 血液出量统计查询
     * @param
     * @return 各种血液出量
     */
    @Override
    public List<Map<String, Object>> getBloodOutReport(List<Map<String, Object>> bloodIdList) {

        List listId = new ArrayList();
        for (int i = 1; i < bloodIdList.size(); i++) {
            String Id = (String) bloodIdList.get(i).get("blood_id");
            listId.add(Id);
        }
        QueryWrapper<BloodStock> wrapperOut = new QueryWrapper<>();
        wrapperOut
                .select(
                        getParamSql(BloodStock::getBloodVariety),
                        getParamSql(BloodStock::getAboBloodType),
                        getParamSql(BloodStock::getRhBloodType),
                        "IFNULL(sum(unit_volume),0)  as OutHp")
                .lambda()
                .groupBy(BloodStock::getBloodVariety,
                        BloodStock::getAboBloodType,
                        BloodStock::getRhBloodType
                )
                .in(BloodStock::getBloodId,listId);
        List<Map<String, Object>> listOut = this.listMaps(wrapperOut);
        return listOut;
    }




}




